import {v4 as uuidv4} from 'uuid';
import {director} from 'cc';
import {ClientMessage, ServerMessage} from "db://assets/proto/new-world-ws/v1/ws";
import {
    FishAttackRecordReply, FishBattleCompleteReply,
    FishDeadReply,
    FishEarnReply,
    FishExploreReply,
    FishGrowthReply, FishMagicPowerRecoverReply, FishMoveCompleteReply, FishPreAttackReply,
    FishRecoverReply,
    FishStayReply
} from "db://assets/proto/new-world-ws/v1/internal";
import {GameEvent} from "db://assets/script/game-event";
import {CityDateChange} from "db://assets/script/common/events/city-events/city-date-change";
import {FishCoreChangeEvent} from "db://assets/script/common/events/fish-events/fish-core-change-event";
import Long from "long";
import {FishStatus} from "db://assets/proto/shared/v1/biz";
import {lobby} from "db://assets/script/lobby";
import {showAlert} from "db://assets/script/game/alert/alert";

enum FishMessageType {
    empty = "empty",
    dead = "dead",
    attack_record = "attack_record",
    growth = "growth",
    earn = "earn",
    explore = "explore",
    recover = "recover",
    energy_recover = "energy_recover",
    stay = "stay",
    move_complete = "move_complete",
    attack_begin = "attack_begin",
    battle_complete = "battle_complete",
}

enum CityMessageType {
    buildingBuild = "ws_building_build",
    buildingRemove = "ws_building_remove",
    buildingUpgrade = "ws_building_upgrade",
    buildingUpgradeCheck = "ws_building_upgrade_check",
    buildingRemoveCheck = "ws_building_remove_check",
    buildingMove = "ws_building_move",
}

const CityMessages: string[] = [CityMessageType.buildingBuild, CityMessageType.buildingRemove, CityMessageType.buildingUpgrade, CityMessageType.buildingMove, CityMessageType.buildingUpgradeCheck, CityMessageType.buildingRemoveCheck];

class Socket {
    ws: WebSocket | null = null;
    // url: string = "ws://118.25.168.135:7001/v1/ws";
    login: boolean = false;
    // url: string = "ws://192.168.10.103:7001/v1/ws";
    url: string = "ws://127.0.0.1:7001/v1/ws";

    connect(u: string, t: string, call?: Function, ct = 1) {
        const wsUri = this.url + "?u=" + u + "&t=" + t + "&ct=" + ct;
        this.ws = new WebSocket(wsUri);
        this.ws.binaryType = "arraybuffer";
        this.ws.onopen = () => {
            console.log("socket open");
            this.login = true;
            call && call();
            setInterval(() => {
                if (this.ws?.readyState == this.ws?.OPEN) {
                    const data = ClientMessage.create({
                        msgId: uuidv4(),
                        type: "ping",
                        key: "",
                    })
                    this.sendMessage(data);
                }
            }, 5 * 1000)
        }
        this.ws.onmessage = (e) => {
            const data = ServerMessage.decode(new Uint8Array(e.data))
            this.emitMessage(data)
        }
        this.ws.onclose = () => {
            let notifyTitle = '网络连接已断开'
            let notifyContent = '网络连接已断开，请重新进入游戏'
            console.log("socket close");
            if (!this.login) {
                localStorage.removeItem('uid')
                localStorage.removeItem('world-access-token')
                notifyContent = '登录过期，请重新登录'
            }
            showAlert(notifyTitle, notifyContent, () => {
                director.loadScene('boot')
            }, () => {
                director.loadScene('boot')
            })
        }
        this.ws.onerror = () => {
            let notifyTitle = '网络连接已断开'
            let notifyContent = '网络连接已断开，请重新进入游戏'
            if (!this.login) {
                localStorage.removeItem('uid')
                localStorage.removeItem('world-access-token')
                notifyContent = '登录过期，请重新登录'
            }
            showAlert(notifyTitle, notifyContent, () => {
                director.loadScene('boot')
            }, () => {
                director.loadScene('boot')
            })
        }
    }

    sendMessage(data: ClientMessage) {
        let buffer = ClientMessage.encode(data).finish();
        this.ws?.send(buffer);
    }

    emitMessage(data: ServerMessage) {
        // let fish = userinfo.getFishs()[0];
        // console.log(data);
        if (data.type === FishMessageType.empty) {

        } else if (data.type === FishMessageType.dead) {
            const body = FishDeadReply.decode(data.body);
            director.emit(GameEvent.fishBeginDead, body)
            // console.log(body)
        } else if (data.type === FishMessageType.attack_begin) {
            const body = FishPreAttackReply.decode(data.body);
            // console.log("攻击开始事件：", body)
            director.emit(GameEvent.fishBeginBattle, body)
        } else if (data.type === FishMessageType.attack_record) {
            const body = FishAttackRecordReply.decode(data.body);
            // console.log("攻击事件：", body)
            director.emit(GameEvent.fishInBattle, body)
        } else if (data.type === FishMessageType.growth) {
            const body = FishGrowthReply.decode(data.body);
            director.emit(GameEvent.fishBeginGrowth, body)
        } else if (data.type === FishMessageType.earn) {
            const body = FishEarnReply.decode(data.body);
            director.emit(GameEvent.fishBeginEarn, body)
            // console.log(body)
        } else if (data.type === FishMessageType.explore) {
            const body = FishExploreReply.decode(data.body);
            director.emit(GameEvent.fishBeginExplore, body)
            // console.log(body)
        } else if (data.type === FishMessageType.recover) {
            const body = FishRecoverReply.decode(data.body);
            director.emit(GameEvent.fishBeginRecover, body)
            // console.log(body)
        } else if (data.type === FishMessageType.energy_recover) {
            const body = FishMagicPowerRecoverReply.decode(data.body);
            director.emit(GameEvent.fishBeginEnergyRecover, body)
            // console.log(body)
        } else if (data.type === FishMessageType.stay) {
            const body = FishStayReply.decode(data.body);
            director.emit(GameEvent.fishBeginStay, body)
            // console.log(body)
        } else if (data.type === FishMessageType.move_complete) {
            const body = FishMoveCompleteReply.decode(data.body);
            director.emit(GameEvent.fishMoveComplete, body)
        } else if (data.type === FishMessageType.battle_complete) {
            const body = FishBattleCompleteReply.decode(data.body);
            director.emit(GameEvent.fishBattleComplete, body)
        } else if (CityMessages.indexOf(data.type) != -1) {
            director.emit(GameEvent.cityDataChange, new CityDateChange(data.headers['req-id']!, data.body))
        }
    }

    closeConnect() {
        this.ws?.close();
        this.ws = null
    }
}

export const socket = new Socket();